home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 May: Tool Chest / Dev.CD May 97 TC.toast / Sample Code / Snippets / Files / AS Authenticator / AS Authenticator.c < prev   
Encoding:
Text File  |  1996-01-25  |  9.7 KB  |  322 lines  |  [TEXT/CWIE]

  1.     //
  2.     //    This code sample answers the question: "How can I ask an
  3.     //    AppleShare server to authenticate an account/password pair
  4.     //    without mounting a volume?"
  5.     //    
  6.     //    It attempts to mount a volume with a name which is known to
  7.     //    be invalid. If VolumeMount claims the password didn't
  8.     //    work, then it didn't. If VolumeMount claims the volume
  9.     //    could not be mounted, then the password was valid.
  10.     //    
  11.     //    This is 100% predictable behavior and doesn't rely on any
  12.     //    hacks. However, it does fall into the category of
  13.     //    empirically discovered undocumented behavior. Specifically,
  14.     //    it counts on the AppleShare server authenticating before
  15.     //    searching for a volume of the specified name.
  16.     //    
  17.     //    You should exercise appropriate caution in making use of
  18.     //    this code. More detailed warnings below.
  19.     //
  20.     //    Complaints and kudos to:
  21.     //
  22.     //        Pete Gontier
  23.     //        Apple Macintosh Developer Technical Support
  24.     //        <gurgle@apple.com>
  25.     //
  26.  
  27. #define SystemSevenOrLater        1
  28. #define OLDROUTINELOCATIONS        0
  29. #define OLDROUTINENAMES            0
  30.  
  31. #ifndef __ERRORS__
  32. #    include <Errors.h>
  33. #endif
  34.  
  35. #ifndef __FILES__
  36. #    include <Files.h>
  37. #endif
  38.  
  39. #ifndef __GESTALT__
  40. #    include <Gestalt.h>
  41. #endif
  42.  
  43. #ifndef __STRINGS__
  44. #    include <Strings.h>
  45. #endif
  46.  
  47. typedef unsigned char Str8 [9];
  48.  
  49. #if GENERATINGPOWERPC
  50. #pragma options align=mac68k
  51. #endif
  52. struct MyAFPVolMountInfo
  53. {
  54.     short length;                /* length of this record */
  55.     VolumeType media;            /* type of media, always AppleShareMediaType */
  56.     short flags;                /* 0 = normal mount; set bit 0 to inhibit greeting messages */
  57.     char nbpInterval;            /* NBP interval parameter; 7 is a good choice */
  58.     char nbpCount;                /* NBP count parameter; 5 is a good choice */
  59.     short uamType;                /* User Authentication Method */
  60.     short zoneNameOffset;        /* offset from start of record to zoneName */
  61.     short serverNameOffset;        /* offset from start of record to serverName */
  62.     short volNameOffset;        /* offset from start of record to volName */
  63.     short userNameOffset;        /* offset from start of record to userName */
  64.     short userPasswordOffset;    /* offset from start of record to userPassword */
  65.     short volPasswordOffset;    /* offset from start of record to volPassword */
  66.     Str31 zoneName;                /* server's AppleTalk zone name */                    
  67.     Str31 serverName;            /* server name */                    
  68.     Str27 volName;                /* volume name */                    
  69.     Str31 userName;                /* user name (zero length Pascal string for guest) */
  70.     Str8 userPassword;            /* user password (zero length Pascal string if no user password) */                    
  71.     char filler1;                /* to word align volPassword */
  72.     Str8 volPassword;            /* volume password (zero length Pascal string if no volume password) */                    
  73.     char filler2;                /* to end record on word boundry */
  74. };
  75. #if GENERATINGPOWERPC
  76. #pragma options align=reset
  77. #endif
  78.  
  79. typedef struct MyAFPVolMountInfo MyAFPVolMountInfo;
  80. typedef MyAFPVolMountInfo *MyAFPVolMountInfoPtr, **MyAFPVolMountInfoHandle;
  81.  
  82. static pascal OSErr GetIndVRefNum (unsigned short ioVolIndex, short *vRefNum)
  83. {
  84.     OSErr err = noErr;
  85.     ParamBlockRec pbr;
  86.  
  87.     pbr.volumeParam.ioCompletion    = nil;
  88.     pbr.volumeParam.ioNamePtr        = nil;
  89.     pbr.volumeParam.ioVolIndex        = ioVolIndex;
  90.  
  91.     if (!(err = PBGetVInfoSync (&pbr)))
  92.         *vRefNum = pbr.volumeParam.ioVRefNum;
  93.     else
  94.         *vRefNum = 0;
  95.  
  96.     return err;
  97. }
  98.  
  99. static pascal OSErr GetVolParms (short vRefNum, GetVolParmsInfoBuffer *gvpibp)
  100. {
  101.     HParamBlockRec hpbr;
  102.  
  103.     hpbr.ioParam.ioCompletion    = nil;
  104.     hpbr.ioParam.ioNamePtr        = nil;
  105.     hpbr.ioParam.ioVRefNum        = vRefNum;
  106.     hpbr.ioParam.ioBuffer        = (Ptr) gvpibp;
  107.     hpbr.ioParam.ioReqCount        = sizeof (*gvpibp);
  108.  
  109.     return PBHGetVolParmsSync (&hpbr);
  110. }
  111.  
  112. static pascal OSErr GetVolMountInfoSize (short vRefNum, unsigned short *size)
  113. {
  114.     ParamBlockRec pbr;
  115.  
  116.     pbr.ioParam.ioCompletion    = nil;
  117.     pbr.ioParam.ioVRefNum        = vRefNum;
  118.     pbr.ioParam.ioBuffer        = (Ptr) size;
  119.  
  120.     return PBGetVolMountInfoSize (&pbr);
  121. }
  122.  
  123. static pascal OSErr GetVolMountInfo (short vRefNum, VolMountInfoPtr vmip)
  124. {
  125.     ParamBlockRec pbr;
  126.  
  127.     pbr.ioParam.ioCompletion    = nil;
  128.     pbr.ioParam.ioVRefNum        = vRefNum;
  129.     pbr.ioParam.ioBuffer        = (Ptr) vmip;
  130.  
  131.     return PBGetVolMountInfo (&pbr);
  132. }
  133.  
  134. static pascal OSErr VolumeMount (VolMountInfoPtr vmip)
  135. {
  136.     ParamBlockRec pbr;
  137.  
  138.     pbr.ioParam.ioCompletion    = nil;
  139.     pbr.ioParam.ioBuffer        = (Ptr) vmip;
  140.  
  141.     return PBVolumeMount (&pbr);
  142. }
  143.  
  144. static pascal    void    BuildAFPVolMountInfo(    short theFlags,
  145.                                                 char theNBPInterval,
  146.                                                 char theNBPCount,
  147.                                                 short theUAMType,
  148.                                                 Str31 theZoneName,
  149.                                                 Str31 theServerName,
  150.                                                 Str27 theVolName,
  151.                                                 Str31 theUserName,
  152.                                                 Str8 theUserPassWord,
  153.                                                 Str8 theVolPassWord,
  154.                                                 VolMountInfoPtr vmip)
  155. {
  156.     MyAFPVolMountInfoPtr theAFPInfo = (MyAFPVolMountInfoPtr) vmip;
  157.  
  158.     /* Fill in an AFPVolMountInfo record that can be passed to VolumeMount */
  159.     theAFPInfo->length = sizeof(MyAFPVolMountInfo);
  160.     theAFPInfo->media = AppleShareMediaType;
  161.     theAFPInfo->flags = theFlags;
  162.     theAFPInfo->nbpInterval = theNBPInterval;
  163.     theAFPInfo->nbpCount = theNBPCount;
  164.     theAFPInfo->uamType = theUAMType;
  165.     theAFPInfo->zoneNameOffset = (short)((long)theAFPInfo->zoneName - (long)theAFPInfo);
  166.     theAFPInfo->serverNameOffset = (short)((long)theAFPInfo->serverName - (long)theAFPInfo);
  167.     theAFPInfo->volNameOffset = (short)((long)theAFPInfo->volName - (long)theAFPInfo);
  168.     theAFPInfo->userNameOffset = (short)((long)theAFPInfo->userName - (long)theAFPInfo);
  169.     theAFPInfo->userPasswordOffset = (short)((long)theAFPInfo->userPassword - (long)theAFPInfo);
  170.     theAFPInfo->volPasswordOffset = (short)((long)theAFPInfo->volPassword - (long)theAFPInfo);
  171.     
  172.     BlockMoveData(theZoneName, theAFPInfo->zoneName, theZoneName[0] + 1);
  173.     BlockMoveData(theServerName, theAFPInfo->serverName, theServerName[0] + 1);
  174.     BlockMoveData(theVolName, theAFPInfo->volName, theVolName[0] + 1);
  175.     BlockMoveData(theUserName, theAFPInfo->userName, theUserName[0] + 1);
  176.     BlockMoveData(theUserPassWord, theAFPInfo->userPassword, theUserPassWord[0] + 1);
  177.     BlockMoveData(theVolPassWord, theAFPInfo->volPassword, theVolPassWord[0] + 1);
  178. }
  179.  
  180. /*****************************************************************************/
  181.  
  182. static pascal OSErr ExtractAFPVolMountInfo (    VolMountInfoPtr theVolMountInfo,
  183.                                                 short *theFlags,
  184.                                                 short *theUAMType,
  185.                                                 StringPtr theZoneName,
  186.                                                 StringPtr theServerName,
  187.                                                 StringPtr theVolName,
  188.                                                 StringPtr theUserName    )
  189. {
  190.     OSErr        error;
  191.     StringPtr    tempPtr;
  192.         
  193.     /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */
  194.     if ( theVolMountInfo->media == AppleShareMediaType )
  195.     {
  196.         MyAFPVolMountInfoPtr theAFPInfo = (MyAFPVolMountInfoPtr) theVolMountInfo;
  197.  
  198.         *theFlags = theAFPInfo->flags;
  199.         *theUAMType = theAFPInfo->uamType;
  200.         
  201.         tempPtr = (StringPtr)((long)theAFPInfo + theAFPInfo->zoneNameOffset);
  202.         BlockMoveData(tempPtr, theZoneName, tempPtr[0] + 1);
  203.         
  204.         tempPtr = (StringPtr)((long)theAFPInfo + theAFPInfo->serverNameOffset);
  205.         BlockMoveData(tempPtr, theServerName, tempPtr[0] + 1);
  206.         
  207.         tempPtr = (StringPtr)(StringPtr)((long)theAFPInfo + theAFPInfo->volNameOffset);
  208.         BlockMoveData(tempPtr, theVolName, tempPtr[0] + 1);
  209.         
  210.         tempPtr = (StringPtr)((long)theAFPInfo + theAFPInfo->userNameOffset);
  211.         BlockMoveData(tempPtr, theUserName, tempPtr[0] + 1);
  212.         
  213.         error = noErr;
  214.     }
  215.     else
  216.     {
  217.         error = paramErr;
  218.     }
  219.     
  220.     return ( error );
  221. }
  222.  
  223. static pascal OSErr Authenticate (VolMountInfoPtr volMountInfoP)
  224. {
  225.     OSErr err = noErr;
  226.  
  227.     short flags;
  228.     short uamType;
  229.     Str31 zoneName;
  230.     Str31 serverName;
  231.     Str27 volName;
  232.     Str31 userName;
  233.  
  234.     if (!(err = ExtractAFPVolMountInfo
  235.         (volMountInfoP,&flags,&uamType,zoneName,serverName,volName,userName)))
  236.     {
  237.         StringPtr    volPassword        = "\p",
  238.                     userPassword    = "\pFoo",
  239.                     volName            = "\pin:valid";
  240.  
  241.         BuildAFPVolMountInfo
  242.             (flags,0,0,uamType,
  243.                 zoneName,serverName,volName,userName,userPassword,volPassword,
  244.                     volMountInfoP);
  245.  
  246.         err = VolumeMount (volMountInfoP);
  247.  
  248.         //    
  249.         //    NOTE: unless you have a user password "Foo", at this point
  250.         //    'err' will indicate a password rejection (-5203), EVEN
  251.         //    THOUGH the volume name is bogus as well. If the password is
  252.         //    valid, 'err' will contain no-such-volume (nsvErr, -35),
  253.         //    because there is in fact no such volume as 'volName', which
  254.         //    is of course because such a volume name is impossible.
  255.         //    
  256.         //    NOTE 2: This works ONLY because AppleShare servers with
  257.         //    which I tested authenticate a user/password pair BEFORE
  258.         //    attempting to find a volume by the given name. If
  259.         //    AppleShare ever changes, this code will break. In other
  260.         //    words, this code relies on an uncontrollable sequence of
  261.         //    events on another machine.
  262.         //
  263.         //    NOTE 3: If this scheme breaks, VolumeMount will most probably
  264.         //    produce nsvErr even for valid account/password pairs.
  265.         //    IN NO CASE WILL ANY VOLUME BE MOUNTED.
  266.         //
  267.     }
  268.  
  269.     return err;
  270. }
  271.  
  272. void main (void)
  273. {
  274.     //
  275.     //    'main' theory of operation: find an AppleShare volume,
  276.     //    get (most of) the info needed to mount it, unmount it,
  277.     //    attempt to mount it again as described above. NOTE:
  278.     //    'Authenticate' *always* returns an error, so the loop's
  279.     //    exit conditions are fulfilled when the first AppleShare
  280.     //    volume is found and unmounted.
  281.     //
  282.  
  283.     OSErr            err;
  284.     unsigned short    ioVolIndex = 1;
  285.  
  286.     do
  287.     {
  288.         short vRefNum;
  289.  
  290.         err = GetIndVRefNum (ioVolIndex, &vRefNum);
  291.         if (err == nsvErr)
  292.             { err = noErr; break; }
  293.         else if (!err)
  294.         {
  295.             GetVolParmsInfoBuffer gvpib;
  296.             if (!(err = GetVolParms (vRefNum, &gvpib)))
  297.             {
  298.                 unsigned short bufSize;
  299.                 err = GetVolMountInfoSize (vRefNum, &bufSize);
  300.                 if (err == -50) // vol does not support mount info
  301.                     err = noErr;
  302.                 else if (!err)
  303.                 {
  304.                     VolMountInfoPtr volMountInfoP = (VolMountInfoPtr) NewPtr (bufSize);
  305.                     if (!(err = MemError ( )))
  306.                     {
  307.                         if (!(err = GetVolMountInfo (vRefNum, volMountInfoP)))
  308.                             if (volMountInfoP->media == AppleShareMediaType)
  309.                                 if (!(err = UnmountVol (nil, vRefNum)))
  310.                                     err = Authenticate (volMountInfoP);
  311.  
  312.                         DisposePtr ((Ptr) volMountInfoP);
  313.                     }
  314.                 }
  315.             }
  316.         }
  317.  
  318.         ++ioVolIndex;
  319.     }
  320.     while (!err);
  321. }
  322.